package com.xbongbong.paas.service.workflow.setting.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.config.enums.WorkflowTriggerMethodEnum;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasAppEntity;
import com.xbongbong.paas.domain.entity.PaasFormEntity;
import com.xbongbong.paas.domain.entity.PaasMenuEntity;
import com.xbongbong.paas.domain.entity.PaasStageEntity;
import com.xbongbong.paas.domain.entity.StageProcessEntity;
import com.xbongbong.paas.domain.entity.StageWorkflowEntity;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.EnableEnum;
import com.xbongbong.paas.enums.MenuTypeEnum;
import com.xbongbong.paas.enums.ProcessSaasFormEnum;
import com.xbongbong.paas.enums.StageWorkflowTriggerTypeEnum;
import com.xbongbong.paas.enums.WorkflowLinkBusinessTypeEnum;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.sys.help.PackageHelp;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.help.WorkflowHelp;
import com.xbongbong.paas.help.WorkflowNodeHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.PaasMenuModel;
import com.xbongbong.paas.model.PaasStageModel;
import com.xbongbong.paas.model.StageProcessModel;
import com.xbongbong.paas.model.StageWorkflowModel;
import com.xbongbong.paas.pojo.dto.OptionalRangeDTO;
import com.xbongbong.paas.pojo.workflow.WorkflowNodeTreePojo;
import com.xbongbong.paas.pojo.workflow.settings.WorkflowGetDetailPojo;
import com.xbongbong.paas.pojo.workflow.settings.WorkflowGetPojo;
import com.xbongbong.paas.pojo.workflow.settings.WorkflowListPoJo;
import com.xbongbong.paas.pojo.workflow.settings.WorkflowPermissionPojo;
import com.xbongbong.paas.pojo.workflow.settings.WorkflowPojo;
import com.xbongbong.paas.pojo.workflow.settings.WorkflowVersionPojo;
import com.xbongbong.paas.pojo.workflow.settings.dto.WorkFlowListDTO;
import com.xbongbong.paas.pojo.workflow.settings.dto.WorkflowAddDTO;
import com.xbongbong.paas.pojo.workflow.settings.dto.WorkflowArchiveDTO;
import com.xbongbong.paas.pojo.workflow.settings.dto.WorkflowDeleteDTO;
import com.xbongbong.paas.pojo.workflow.settings.dto.WorkflowDeleteVersionDTO;
import com.xbongbong.paas.pojo.workflow.settings.dto.WorkflowEnableDTO;
import com.xbongbong.paas.pojo.workflow.settings.dto.WorkflowGetDTO;
import com.xbongbong.paas.pojo.workflow.settings.dto.WorkflowGetDetailDTO;
import com.xbongbong.paas.pojo.workflow.settings.dto.WorkflowLinkListDTO;
import com.xbongbong.paas.pojo.workflow.settings.dto.WorkflowNewVersionDTO;
import com.xbongbong.paas.pojo.workflow.settings.dto.WorkflowSortDTO;
import com.xbongbong.paas.pojo.workflow.settings.dto.WorkflowSortListDTO;
import com.xbongbong.paas.pojo.workflow.settings.dto.WorkflowUpdateDTO;
import com.xbongbong.paas.pojo.workflow.settings.dto.WorkflowUpdateNameDTO;
import com.xbongbong.paas.pojo.workflow.settings.dto.WorkflowVersionListDTO;
import com.xbongbong.paas.pojo.workflow.settings.vo.WorkFlowListVO;
import com.xbongbong.paas.pojo.workflow.settings.vo.WorkflowAddVO;
import com.xbongbong.paas.pojo.workflow.settings.vo.WorkflowArchiveVO;
import com.xbongbong.paas.pojo.workflow.settings.vo.WorkflowDeleteVO;
import com.xbongbong.paas.pojo.workflow.settings.vo.WorkflowDeleteVersionVO;
import com.xbongbong.paas.pojo.workflow.settings.vo.WorkflowEnableVO;
import com.xbongbong.paas.pojo.workflow.settings.vo.WorkflowGetDetailVO;
import com.xbongbong.paas.pojo.workflow.settings.vo.WorkflowGetVO;
import com.xbongbong.paas.pojo.workflow.settings.vo.WorkflowLinkListVO;
import com.xbongbong.paas.pojo.workflow.settings.vo.WorkflowNewVersionVO;
import com.xbongbong.paas.pojo.workflow.settings.vo.WorkflowSortListVO;
import com.xbongbong.paas.pojo.workflow.settings.vo.WorkflowSortVO;
import com.xbongbong.paas.pojo.workflow.settings.vo.WorkflowUpdateNameVO;
import com.xbongbong.paas.pojo.workflow.settings.vo.WorkflowUpdateVO;
import com.xbongbong.paas.pojo.workflow.settings.vo.WorkflowVersionListVO;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.service.stage.StageHandle;
import com.xbongbong.paas.service.stage.StageHandleFactory;
import com.xbongbong.paas.service.workflow.setting.WorkflowNodeService;
import com.xbongbong.paas.service.workflow.setting.WorkflowNodeSettings;
import com.xbongbong.paas.service.workflow.setting.WorkflowSetService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.helper.PageHelper;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.PageHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.FormUtil;
import com.xbongbong.paas.util.WorkflowNodeUtil;
import com.xbongbong.pro.constant.BasePackageConstant;
import com.xbongbong.pro.domain.entity.FormConfigEntity;
import com.xbongbong.pro.enums.DistributorMarkEnum;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.ValueAddedTypeEnum;
import com.xbongbong.pro.enums.errorcodes.ProErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.permission.enums.ProPermissionAliasEnum;
import com.xbongbong.pro.enums.workflow.TriggerEventTypeEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.WorkOrderFormEntity;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.FormConfigModel;
import com.xbongbong.saas.model.WorkOrderFormModel;
import com.xbongbong.saas.service.toolbox.help.UpdatePackageRedisService;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.help.ProPermissionHelp;
import com.xbongbong.sys.model.UserModel;
import com.xbongbong.workflow.domain.entity.WorkflowEntity;
import com.xbongbong.workflow.domain.entity.WorkflowNodeEntity;
import com.xbongbong.workflow.domain.entity.WorkflowTaskEntity;
import com.xbongbong.workflow.domain.entity.ext.WorkflowNodeEntityExt;
import com.xbongbong.workflow.enums.WorkflowNodeTypeEnum;
import com.xbongbong.workflow.model.WorkflowModel;
import com.xbongbong.workflow.model.WorkflowNodeModel;
import com.xbongbong.workflow.model.WorkflowTaskModel;
import com.xbongbong.workflow.pojo.nodes.WorkflowNodePojo;
import org.apache.commons.collections4.CollectionUtils;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author 吴峰
 * @date 2021/05/10 10:24
 */
@Service("WorkflowSetService")
public class WorkflowSetServiceImpl implements WorkflowSetService {

    /**
     * 一个表单工作流未归档最大数量
     */
    private static final Integer WORKFLOW_ISARCHIVE_MAX = 50;
    /**
     * 一个表单工作流最大数量
     */
    private static final Integer WORKFLOW_MAX = 550;

    /**
     * 未归档最大数量
     */
    private static final Integer NONE_ARCHIVE = 500;



    private static final Logger LOGGER = LoggerFactory.getLogger(WorkflowSetServiceImpl.class);

    @Resource
    private WorkflowModel workflowModel;
    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private UserModel userModel;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private WorkflowNodeService workflowNodeService;
    @Resource
    private WorkflowNodeModel workflowNodeModel;
    @Resource
    private WorkflowTaskModel workflowTaskModel;
    @Resource
    private WorkflowNodeHelp workflowNodeHelp;
    @Resource
    private Map<Integer, WorkflowNodeSettings> workflowNodeSettingsMap;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private PaasMenuModel paasMenuModel;
    @Resource
    private WorkOrderFormModel workOrderFormModel;
    @Resource
    private FormConfigModel formConfigModel;
    @Resource
    private UpdatePackageRedisService updatePackageRedisService;
    @Resource
    private PackageHelp packageHelp;
    @Resource
    private WorkflowHelp workflowHelp;

    @Resource
    private StageWorkflowModel stageWorkflowModel;
    @Resource
    private StageProcessModel stageProcessModel;
    @Resource
    private PaasStageModel paasStageModel;
    @Resource
    private StageHandleFactory stageHandleFactory;
    @Resource
    private CommonHelp commonHelp;

    @Override
    public WorkFlowListVO list(WorkFlowListDTO workFlowListDTO) throws XbbException {
        try {
            UserVO userVO = workFlowListDTO.getLoginUser();
            Boolean open = userVO.isAdminOrBoss() || ProPermissionHelp.hasThisPermission(workFlowListDTO.getLoginUser(), ProPermissionAliasEnum.PROCESS_SET_OPEN.getAlias());
            Boolean close = userVO.isAdminOrBoss() ||  ProPermissionHelp.hasThisPermission(workFlowListDTO.getLoginUser(), ProPermissionAliasEnum.PROCESS_SET_CLOSE.getAlias());
            Boolean delete = userVO.isAdminOrBoss() ||  ProPermissionHelp.hasThisPermission(workFlowListDTO.getLoginUser(), ProPermissionAliasEnum.WORKFLOW_DELETE.getAlias());

            Boolean edit = userVO.isAdminOrBoss() ||  ProPermissionHelp.hasThisPermission(workFlowListDTO.getLoginUser(), ProPermissionAliasEnum.PROCESS_SET_UPDATE.getAlias());
            boolean view = userVO.isAdminOrBoss() || ProPermissionHelp.hasThisPermission(userVO, ProPermissionAliasEnum.PROCESS_SET_VIEW.getAlias());
            Boolean add = edit;
            boolean workflow = true;
            Integer totalValue = 0;
            Integer usedValue = 0;
            String usageRate = "100%";
            Integer notMuch = 0;

            String corpid = workFlowListDTO.getCorpid();
            JSONObject jsonObject = updatePackageRedisService.getValueAddInfo(corpid, ValueAddedTypeEnum.WORKFLOW, null, null);
            if (Objects.nonNull(jsonObject)) {
                totalValue = jsonObject.getInteger("totalValue");
                totalValue = totalValue == null || Objects.equals(0, totalValue) ? BasePackageConstant.FreePackage.WORKFLOW :totalValue;
                usedValue = jsonObject.getInteger("usedValue");
                usedValue = usedValue == null ? 0 : usedValue;
                BigDecimal bigDecimal = new BigDecimal(usedValue.toString()).divide(new BigDecimal(totalValue.toString()), 4, BigDecimal.ROUND_HALF_UP);
                bigDecimal = new BigDecimal(1).subtract(bigDecimal);
                double d = bigDecimal.doubleValue() * 100;
                if (d <= 10D) {
                    notMuch = 1;
                }
                usageRate = d + "%";
            }
            if (Objects.nonNull(workFlowListDTO.getFormId())) {
                PaasFormEntity paasFormEntity = proFormHelp.getPaasForm(workFlowListDTO.getFormId(), workFlowListDTO.getBusinessType(), corpid);
                workflow = !(!FormUtil.haveUserPermission(paasFormEntity.getBusinessType(), paasFormEntity.getSaasMark(), paasFormEntity.getDistributorMark())
                        && (Objects.equals(DistributorMarkEnum.DISTRIBUTOR.getCode(), paasFormEntity.getDistributorMark())
                        || Objects.equals(paasFormEntity.getSaasMark(), SaasMarkEnum.SAAS.getCode()) && !ProcessSaasFormEnum.workflowApproveNode(paasFormEntity.getBusinessType())));
            }
            WorkflowPermissionPojo workflowPermissionPojo = new WorkflowPermissionPojo(add, open, close, edit, delete, workflow);
            if (!view) {
                return new WorkFlowListVO(new ArrayList<>(), new PageHelper(), workflowPermissionPojo, totalValue, usedValue, usageRate, notMuch);
            }
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID, corpid);
            param.put(StringConstant.FORM_ID, workFlowListDTO.getFormId());
            param.put(StringConstant.SAAS_MARK, workFlowListDTO.getSaasMark());
            param.put(StringConstant.BUSINESS_TYPE, workFlowListDTO.getBusinessType());
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("nameLike", workFlowListDTO.getNameLike());
            param.put("currentVersion", BasicConstant.ONE);
            param.put("orderByStr", "update_time desc ");
            if (!Objects.isNull(workFlowListDTO.getType())) {
                param.put("type", workFlowListDTO.getType());
            }
            PageHelper pageHelper = PageHelperUtil.getPageHelper(param, workflowModel, workFlowListDTO.getPage(), workFlowListDTO.getPageSize());
            List<WorkflowEntity> list = (List<WorkflowEntity>) PageHelperUtil.getEntityList(param, pageHelper, workflowModel);
            if (CollectionsUtil.isEmpty(list)) {
                return new WorkFlowListVO(new ArrayList<>(), new PageHelper(), workflowPermissionPojo, totalValue, usedValue, usageRate, notMuch);
            }
            Set<Long> appIdSet = new HashSet<>();
            Set<Long> workOrderIdSet = new HashSet<>();
            Set<Long> formIdSet = new HashSet<>();
            Set<String> creatorIdSet = new HashSet<>();
            list.forEach(item->{
                appIdSet.add(item.getAppId());
                creatorIdSet.add(item.getCreatorId());
                if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), item.getBusinessType())) {
                    workOrderIdSet.add(item.getFormId());
                } else {
                    formIdSet.add(item.getFormId());
                }
            });
            // 获取应用名称
            Map<String, Object> appParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            appParam.put(StringConstant.CORPID, workFlowListDTO.getCorpid());
            appParam.put(StringConstant.IDIN, appIdSet);
            appParam.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            List<PaasAppEntity> appList = paasAppModel.list(appParam);
            Map<Long, String> appNameMap = new HashMap<>(appList.size());
            appList.forEach(item-> appNameMap.put(item.getId(), item.getName()));
            // 获取应用名称
            List<UserEntity> userList = userModel.findEntitysByUserIds(new ArrayList<>(creatorIdSet), corpid);
            Map<String, String> userNameMap = new HashMap<>(userList.size());
            userList.forEach(item->userNameMap.put(item.getUserId(), item.getName()));

            Map<Long, PaasFormEntity> formEntityMap = proFormHelp.getFormMap(formIdSet, corpid, DelEnum.NORMAL.getDel());
            Map<Long, WorkOrderFormEntity> workFormEntityMap = proFormHelp.getWorkOrderFormMap(workOrderIdSet, corpid, DelEnum.NORMAL.getDel());


             List<WorkflowListPoJo> workflowList = new ArrayList<>();
            list.forEach(item->{
                if (!appNameMap.containsKey(item.getAppId())) {
                    return;
                }
                String appName = appNameMap.get(item.getAppId());
                if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(),item.getBusinessType())) {
                    if (!workFormEntityMap.containsKey(item.getFormId())) {
                        return;
                    }
                    appName = appName+ StringConstant.POINT + workFormEntityMap.get(item.getFormId()).getName();
                } else {
                    if (!formEntityMap.containsKey(item.getFormId())) {
                        return;
                    }
                    appName = appName+ StringConstant.POINT + formEntityMap.get(item.getFormId()).getName();
                }
                String lastEnableTime = DateTimeUtil.getStringEpochSecond(item.getLastEnableTime(), DateTimeUtil.SDFYMDHM);
                if (Objects.equals(1, item.getEnable())) {
                    lastEnableTime = lastEnableTime + I18nMessageUtil.getMessage(PaasConstant.ENABLE);
                } else if (Objects.equals(0, item.getEnable())){
                    lastEnableTime = lastEnableTime + I18nMessageUtil.getMessage(PaasConstant.CLOSED);
                }
                String triggerEventInfo = TriggerEventTypeEnum.getMemoByType(item.getTriggerEventType());
                WorkflowListPoJo workFlowPojo = new WorkflowListPoJo(item.getId(), item.getName(), appName, item.getType(), triggerEventInfo, item.getEnable(),
                        item.getPriority(), lastEnableTime, userNameMap.get(item.getCreatorId()));
                workflowList.add(workFlowPojo);
            });

            return new WorkFlowListVO(workflowList, pageHelper, workflowPermissionPojo, totalValue, usedValue, usageRate, notMuch);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("WorkflowSetServiceImpl.list error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public WorkflowAddVO add(WorkflowAddDTO workflowAddDTO) throws XbbException {
        WorkflowAddVO workflowAddVO = new WorkflowAddVO();
        try {
            String corpid = workflowAddDTO.getCorpid();
            Integer type = workflowAddDTO.getType();
            Long appId = workflowAddDTO.getAppId();
            Long menuId = workflowAddDTO.getMenuId();
            Long formId = workflowAddDTO.getFormId();
            Integer saasMark = workflowAddDTO.getSaasMark();
            Integer businessType = workflowAddDTO.getBusinessType();

            Integer priority = 0;
            if (Objects.equals(type, WorkflowTriggerMethodEnum.FORM.getType())) {
                // 现在只有表单触发工作流的需要查这个进行优先级处理
                Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                params.put("orderByStr", " version_id DESC ");
                params.put(StringConstant.CORPID, corpid);
                params.put(StringConstant.FORM_ID, formId);
                params.put(StringConstant.SAAS_MARK, saasMark);
                params.put(StringConstant.BUSINESS_TYPE, businessType);
                params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
                List<Integer> triggerTypeIn = new ArrayList<>();
                triggerTypeIn.add(workflowAddDTO.getTriggerEventType());
                if (Objects.equals(TriggerEventTypeEnum.ONLY_ADD.getType(), workflowAddDTO.getTriggerEventType())
                        || Objects.equals(TriggerEventTypeEnum.ONLY_UPDATE.getType(), workflowAddDTO.getTriggerEventType())) {
                    triggerTypeIn.add(TriggerEventTypeEnum.ADD_OR_UPDATE.getType());
                } else if (Objects.equals(TriggerEventTypeEnum.ADD_OR_UPDATE.getType(), workflowAddDTO.getTriggerEventType())) {
                    triggerTypeIn.add(TriggerEventTypeEnum.ONLY_ADD.getType());
                    triggerTypeIn.add(TriggerEventTypeEnum.ONLY_UPDATE.getType());
                }
                params.put("triggerEventTypeIn", triggerTypeIn);
                List<WorkflowEntity> workflowList = workflowModel.findEntitys(params);

                if (CollectionsUtil.isNotEmpty(workflowList)) {
                    List<WorkflowEntity> workflowEntityList = workflowList.stream().sorted(Comparator.comparing(WorkflowEntity::getPriority)).collect(Collectors.toList());

                    for (WorkflowEntity item : workflowEntityList) {
                        if (Objects.equals(1, item.getCurrentVersion())) {
                            priority ++;
                            item.setPriority(priority);
                        }
                    }

                    workflowModel.updatePriority(workflowEntityList, corpid);
                }


                priority = priority + 1;
            }

            int versionId = 1;
            long now = DateTimeUtil.getInt();
            String name = workflowAddDTO.getName();
            String version = UUID.randomUUID().toString();
            WorkflowNodePojo workflowNodePojo = workflowAddDTO.getWorkflowNode();
            WorkflowEntity workflowEntity = new WorkflowEntity(corpid, "", name, version, type, workflowAddDTO.getTriggerEventType(), appId, formId,  menuId, saasMark, businessType,
                    priority, 0, 0, now, 0, 0, 0, 2, "v"+ versionId, versionId, BasicConstant.ONE,
                    workflowNodePojo.getUsePermission(), 3, 0, 2, workflowAddDTO.getUserId(),"[]");
            workflowModel.insert(workflowEntity);

            String workflowMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_ADD_WORK), workflowAddDTO.getLoginUserName(), OperateModuleTypeEnum.WORKFLOW.getName(), workflowEntity.getName());
            mongoLogHelp.saveLoggerByInsert(corpid, workflowAddDTO.getUserId(), workflowAddDTO.getLoginUserName(), workflowEntity.getName(), workflowMemo, workflowEntity.getId().toString(), workflowAddDTO.getHttpHeader(), OperateModuleTypeEnum.WORKFLOW, OperateTypeEnum.NEW);

            workflowAddVO.setWorkflowId(workflowEntity.getId());
            List<WorkflowNodeEntity> workflowNodeList = workflowNodeService.addWorkflowNode(corpid, type, workflowEntity.getId(),  workflowNodePojo, workflowAddDTO.getLoginUser(), workflowAddDTO.getHttpHeader(), BasicConstant.ZERO);
            workflowAddVO.setWorkflowNodeId(workflowNodeList.get(0).getId());
            workflowAddVO.setVersion(version);
            String alias = RedisPrefixConstant.ALLOW_EDIT_AFTER_FINISHED;

            FormConfigEntity formConfigEntity = formConfigModel.getByConfig(alias, corpid, workflowEntity.getFormId(), workflowEntity.getSaasMark(), workflowEntity.getBusinessType());
            if (Objects.isNull(formConfigEntity)) {
                FormConfigEntity updateFormConfig = new FormConfigEntity(corpid, formId, saasMark, businessType, alias, "0");
                formConfigModel.insert(updateFormConfig);
            }
        } catch (XbbException e) {
            throw e;
        }catch (Exception e) {
            LOGGER.error("WorkflowSetServiceImpl.add error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return workflowAddVO;
    }


    @Override
    public WorkflowDeleteVO delete(WorkflowDeleteDTO workflowDeleteDTO) throws XbbException {
        WorkflowDeleteVO workflowDeleteVO = new WorkflowDeleteVO();
        try {
            ProPermissionHelp.verifyPermission(workflowDeleteDTO.getLoginUser(), ProPermissionAliasEnum.WORKFLOW_DELETE.getAlias());
            String corpid = workflowDeleteDTO.getCorpid();
            Long workflowId = workflowDeleteDTO.getWorkflowId();
            WorkflowEntity workflowEntity = workflowModel.getByKey(workflowId, corpid);
            if (Objects.isNull(workflowEntity)) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260037);
            }
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put(StringConstant.CORPID, corpid);
            params.put("version", workflowEntity.getVersion());
            params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            List<WorkflowEntity> workflowList = workflowModel.findEntitys(params);
            if (Objects.isNull(workflowList)) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260037);
            }
            List<Long> workflowIdList = new ArrayList<>();

            workflowList.forEach(item->workflowIdList.add(item.getId()));
            params.clear();
            params.put(StringConstant.CORPID, corpid);
            params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            params.put("workflowIdIn", workflowIdList);
            Integer count = workflowTaskModel.getEntityCount(params);
            if (count > 0) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260045);
            }
            // 删除工作流
            workflowModel.deleteBatch(workflowIdList, corpid);
            String workflowMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_WORK), workflowDeleteDTO.getLoginUserName(), OperateModuleTypeEnum.WORKFLOW.getName(), workflowEntity.getName());
            mongoLogHelp.saveLoggerByInsert(corpid, workflowDeleteDTO.getUserId(), workflowDeleteDTO.getLoginUserName(), workflowEntity.getName(), workflowMemo,
                    workflowIdList.toString(), workflowDeleteDTO.getHttpHeader(), OperateModuleTypeEnum.WORKFLOW, OperateTypeEnum.DELETE);

            // 删除工作流的节点
            workflowNodeModel.deleteByWorkflowId(workflowIdList, corpid);

        } catch (XbbException e) {
            throw e;
        }  catch (Exception e) {
            LOGGER.error("WorkflowSetServiceImpl.delete error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return workflowDeleteVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public WorkflowEnableVO enable(WorkflowEnableDTO workflowEnableDTO) throws XbbException {
        String corpid = workflowEnableDTO.getCorpid();
        Long workflowId = workflowEnableDTO.getWorkflowId();
        //获取原工作流节点数（不包括条件块节点）
        Integer oldNodeCount =  workflowHelp.getNodeCount(corpid, workflowId);
        Integer maxCount = commonHelp.maxWorkflowNode(corpid);
        if(oldNodeCount > maxCount && Objects.equals(workflowEnableDTO.getEnable(), EnableEnum.OPEN.getCode())){
            throw new XbbException(ErrorCodeEnum.API_ERROR_260065, String.format(ErrorCodeEnum.API_ERROR_260065.getMsg(), maxCount));
        }
        WorkflowEnableVO workflowEnableVO = new WorkflowEnableVO();
        try {
            boolean enable = workflowEnableDTO.getEnable() == 1 ? true: false;
            if (enable) {
                ProPermissionHelp.verifyPermission(workflowEnableDTO.getLoginUser(), ProPermissionAliasEnum.PROCESS_SET_OPEN.getAlias());
            } else {
                ProPermissionHelp.verifyPermission(workflowEnableDTO.getLoginUser(), ProPermissionAliasEnum.PROCESS_SET_CLOSE.getAlias());
            }
            WorkflowEntity workflowEntity = workflowModel.getByKey(workflowId, corpid);
            if (Objects.isNull(workflowEntity)) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260037);
            }
            WorkflowEntity currentVersionWorkflow = null;
            if (enable) {
                Map<String, Object> param= new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put(StringConstant.CORPID, corpid);
                param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
                param.put("enable", 1);
                param.put("currentVersion", 1);
                Integer count = workflowModel.getEntitysCount(param);
                if (count >= 300) {
                    throw new XbbException(ProErrorCodeEnum.API_ERROR_260049);
                }
                List<WorkflowNodeEntity> nodeList = workflowNodeModel.getWorkflowNodeList(corpid, workflowId, null);

                WorkflowGetPojo workflowGetPojo = workflowNodeHelp.getContent(nodeList, corpid);
                Map<Long, WorkflowNodeEntity> workflowNodeMap = new HashMap<>(nodeList.size());
                boolean includeExecutableNode = false;
                for (WorkflowNodeEntity workflowNodeEntity : nodeList) {
                    if (WorkflowNodeTypeEnum.getExecutableNodeList().contains(workflowNodeEntity.getType())) {
                        // 包含了可执行操作的节点
                        includeExecutableNode = true;
                    }
                    workflowNodeMap.put(workflowNodeEntity.getId(), workflowNodeEntity);
                }
                if (!includeExecutableNode) {
                    // 未包含可执行操作的节点,请至少添加一个
                    throw new XbbException(ProErrorCodeEnum.API_ERROR_260050);
                }
                for (WorkflowNodeEntity item : nodeList) {
                    WorkflowNodeSettings workflowNodeSettings = workflowNodeSettingsMap.get(item.getType());
                    workflowEnableVO = workflowNodeSettings.check(item, workflowNodeMap, workflowGetPojo);
                    if (Objects.equals(workflowEnableVO.getSuccess(), BasicConstant.ZERO)) {
                        workflowEnableVO.setName(item.getName());
                        workflowEnableVO.setNodeId(item.getUid());
                        return workflowEnableVO;
                    }
                }
                param.clear();
                param.put(StringConstant.CORPID, corpid);
                param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
                param.put("version", workflowEntity.getVersion());
                param.put("currentVersion", 1);
                List<WorkflowEntity> list = workflowModel.findEntitys(param);
                if (CollectionsUtil.isNotEmpty(list)) {
                    currentVersionWorkflow = list.get(0);
                }
            }
            // 启用工作流/关闭工作流
            WorkflowEntity update = new WorkflowEntity();
            update.setId(workflowId);
            update.setCorpid(corpid);
            update.setEnable(workflowEnableDTO.getEnable());
            update.setLastEnableTime(DateTimeUtil.getInt());
            update.setCurrentVersion(1);
            update.setUpdateTime(DateTimeUtil.getInt());
            workflowModel.update(update);
            if (Objects.nonNull(currentVersionWorkflow) && !Objects.equals(workflowId, currentVersionWorkflow.getId())) {
                WorkflowEntity updateCurrentVersion = new WorkflowEntity();
                updateCurrentVersion.setId(currentVersionWorkflow.getId());
                updateCurrentVersion.setCorpid(corpid);
                updateCurrentVersion.setCurrentVersion(0);
                updateCurrentVersion.setUpdateTime(DateTimeUtil.getInt());
                updateCurrentVersion.setEnable(0);
                updateCurrentVersion.setLastEnableTime(DateTimeUtil.getInt());
                workflowModel.update(updateCurrentVersion);
            }
            String enableMemo = LogMemoConstant.LOG_MEMO_USER_ENABLE_WORKFLOW;
            OperateTypeEnum operateTypeEnum = OperateTypeEnum.ENABLE;
            if (Objects.equals(0, workflowEnableDTO.getEnable())) {
               enableMemo = LogMemoConstant.LOG_MEMO_USER_CLOSE_WORKFLOW;
               operateTypeEnum = OperateTypeEnum.CLOSE;
            }
            String workflowMemo = String.format(I18nMessageUtil.getMessage(enableMemo), workflowEnableDTO.getLoginUserName(), OperateModuleTypeEnum.WORKFLOW.getName(), workflowEntity.getName());
            mongoLogHelp.saveLoggerByInsert(corpid, workflowEnableDTO.getUserId(), workflowEnableDTO.getLoginUserName(), workflowEntity.getName(), workflowMemo,
                    workflowEntity.getId().toString(), workflowEnableDTO.getHttpHeader(), OperateModuleTypeEnum.WORKFLOW, operateTypeEnum);
            // 更新表单流程标识和菜单类型
            updateFormType(workflowEntity, workflowEnableDTO.getEnable(), workflowEnableDTO);
            workflowEnableVO.setSuccess(1);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("WorkflowSetServiceImpl.enable error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return workflowEnableVO;
    }


    @Override
    public WorkflowGetVO get(WorkflowGetDTO workflowGetDTO) throws XbbException {
        WorkflowGetVO workflowGetVO = new WorkflowGetVO();
        try {
            ProPermissionHelp.verifyPermission(workflowGetDTO.getLoginUser(), ProPermissionAliasEnum.PROCESS_SET_VIEW.getAlias());
            String corpid = workflowGetDTO.getCorpid();
            Long workflowId = workflowGetDTO.getWorkflowId();
            WorkflowEntity workflowEntity = workflowModel.getByKey(workflowId, corpid);
            if (Objects.isNull(workflowEntity)) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260037);
            }
            PaasFormEntity paasFormEntity = proFormHelp.getPaasForm(workflowEntity.getFormId(), workflowEntity.getBusinessType(), corpid);

            // 获取工作流节点
            List<WorkflowNodeEntity> nodeList = workflowNodeModel.getWorkflowNodeList(corpid, workflowId, " priority " + SortOrder.ASC);


            WorkflowGetPojo workflowGetPojo = workflowNodeHelp.getContent(nodeList, corpid);

            List<WorkflowNodeTreePojo> workflowNodeTreeList = workflowNodeHelp.getNodeList(nodeList, workflowGetPojo);
            // 建树
            WorkflowNodeTreePojo workflowNodeTreePojo = WorkflowNodeUtil.buildTree(workflowNodeTreeList);
            workflowGetVO.setWorkflowNodeTree(workflowNodeTreePojo);

            Integer allowEditAfterFinished = 0;
            String alias = RedisPrefixConstant.ALLOW_EDIT_AFTER_FINISHED;

            FormConfigEntity formConfigEntity = formConfigModel.getByConfig(alias, corpid, workflowEntity.getFormId(), workflowEntity.getSaasMark(), workflowEntity.getBusinessType());
            if (Objects.nonNull(formConfigEntity)) {
                allowEditAfterFinished = Integer.valueOf(formConfigEntity.getConfigValue());
            }

            WorkflowPojo workflowPojo = new WorkflowPojo(workflowEntity.getId(), workflowEntity.getCorpid(), workflowEntity.getIcon(), workflowEntity.getName(), workflowEntity.getType(),
                    workflowEntity.getTriggerEventType(), workflowEntity.getAppId(), workflowEntity.getFormId(), workflowEntity.getMenuId(), workflowEntity.getSaasMark(),
                    workflowEntity.getBusinessType(), workflowEntity.getPriority(), workflowEntity.getEnable(), workflowEntity.getIsApprove(), workflowEntity.getLastEnableTime(), allowEditAfterFinished,
                    workflowEntity.getAllowWithdraw(), workflowEntity.getAllowViewLog(), workflowEntity.getAllowViewWhole(), workflowEntity.getEmptyApproverType(), workflowEntity.getVersionName(), workflowEntity.getVersion(), workflowEntity.getVersionId(),
                    workflowEntity.getCurrentVersion(), workflowEntity.getUsePermission(), workflowEntity.getApproverDedup(), workflowEntity.getAutoApprovedPass(), workflowEntity.getIsArchive(),
                    workflowEntity.getRolesWithoutApprove());
            workflowPojo.setFormName(paasFormEntity.getName());
            workflowGetVO.setWorkflow(workflowPojo);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("WorkflowSetServiceImpl.get error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return workflowGetVO;
    }


    @Override
    public WorkflowGetDetailVO getDetail(WorkflowGetDetailDTO workflowGetDetailDTO) throws XbbException {
        try {
            String corpid = workflowGetDetailDTO.getCorpid();
            Long workflowId = workflowGetDetailDTO.getWorkflowId();
            WorkflowEntity workflowEntity = workflowModel.getByKey(workflowId, corpid);
            if (Objects.isNull(workflowEntity)) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260037);
            }
            PaasFormEntity paasFormEntity = proFormHelp.getPaasForm(workflowEntity.getFormId(), workflowEntity.getBusinessType(), corpid);
            Integer allowEditAfterFinished = 0;
            String alias = RedisPrefixConstant.ALLOW_EDIT_AFTER_FINISHED;

            FormConfigEntity formConfigEntity = formConfigModel.getByConfig(alias, corpid, workflowEntity.getFormId(), workflowEntity.getSaasMark(), workflowEntity.getBusinessType());
            if (Objects.nonNull(formConfigEntity)) {
                allowEditAfterFinished = Integer.valueOf(formConfigEntity.getConfigValue());
            }

            WorkflowGetDetailPojo workflowGetDetailPojo = new WorkflowGetDetailPojo(workflowEntity.getPriority(), allowEditAfterFinished, workflowEntity.getAllowWithdraw(), workflowEntity.getAllowViewLog(), workflowEntity.getAllowViewWhole(),
                    workflowEntity.getEmptyApproverType(), workflowEntity.getApproverDedup(), workflowEntity.getAutoApprovedPass(), JSON.parseArray(workflowEntity.getRolesWithoutApprove(), OptionalRangeDTO.class));
            WorkflowGetDetailVO workflowGetDetailVO = new WorkflowGetDetailVO(workflowEntity.getAppId(), workflowEntity.getMenuId(), workflowEntity.getFormId(), paasFormEntity.getName(), workflowEntity.getSaasMark(), workflowEntity.getBusinessType(),workflowId, workflowGetDetailPojo);
            return workflowGetDetailVO;
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("WorkflowSetServiceImpl.getDetail error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    @Override
    public WorkflowUpdateNameVO updateName(WorkflowUpdateNameDTO workflowUpdateNameDTO) throws XbbException {
        WorkflowUpdateNameVO workflowUpdateNameVO = new WorkflowUpdateNameVO();
        try {
            String corpid = workflowUpdateNameDTO.getCorpid();
            Long workflowId = workflowUpdateNameDTO.getWorkflowId();
            WorkflowEntity workflowEntity = workflowModel.getByKey(workflowId, corpid);
            if (Objects.isNull(workflowEntity)) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260037);
            }
            WorkflowEntity entity = new WorkflowEntity();
            entity.setId(workflowId);
            entity.setCorpid(corpid);
            entity.setName(workflowUpdateNameDTO.getName());
            workflowModel.update(entity);
        } catch (Exception e) {
            LOGGER.error("WorkflowSetServiceImpl.updateName error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return workflowUpdateNameVO;
    }


    @Override
    public WorkflowSortListVO sortList(WorkflowSortListDTO workflowSortListDTO) throws XbbException {
        WorkflowSortListVO workflowSortListVO = new WorkflowSortListVO();
        try {
            String corpid = workflowSortListDTO.getCorpid();
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID, corpid);
            param.put(StringConstant.FORM_ID, workflowSortListDTO.getFormId());
            param.put(StringConstant.BUSINESS_TYPE, workflowSortListDTO.getBusinessType());
            param.put(StringConstant.SAAS_MARK, workflowSortListDTO.getSaasMark());
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("currentVersion", BasicConstant.ONE);
            param.put("orderByStr", "priority ASC");
            List<Integer> triggerTypeIn = new ArrayList<>();
            triggerTypeIn.add(workflowSortListDTO.getTriggerType());
            if (Objects.equals(TriggerEventTypeEnum.ONLY_ADD.getType(), workflowSortListDTO.getTriggerType())
                    || Objects.equals(TriggerEventTypeEnum.ONLY_UPDATE.getType(), workflowSortListDTO.getTriggerType())) {
                triggerTypeIn.add(TriggerEventTypeEnum.ADD_OR_UPDATE.getType());
            } else if (Objects.equals(TriggerEventTypeEnum.ADD_OR_UPDATE.getType(), workflowSortListDTO.getTriggerType())) {
                triggerTypeIn.add(TriggerEventTypeEnum.ONLY_ADD.getType());
                triggerTypeIn.add(TriggerEventTypeEnum.ONLY_UPDATE.getType());
            }
            param.put("triggerEventTypeIn", triggerTypeIn);
            List<WorkflowEntity> workflowList = workflowModel.findEntitys(param);
            List<WorkflowListPoJo> resultList = new ArrayList<>();
            workflowList.forEach(item->{
                WorkflowListPoJo workFlowListPoJo = new WorkflowListPoJo(item.getId(), item.getVersion(), item.getName(), item.getPriority());
                resultList.add(workFlowListPoJo);
            });
            workflowSortListVO.setWorkflowList(resultList);

        } catch (Exception e) {
            LOGGER.error("WorkflowSetServiceImpl.sortList error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return workflowSortListVO;
    }

    @Override
    public WorkflowSortVO sort(WorkflowSortDTO workflowSortDTO) throws XbbException {
        WorkflowSortVO workflowSortVO = new WorkflowSortVO();
        try {
            List<WorkflowEntity> list = new ArrayList<>();
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put(StringConstant.CORPID, workflowSortDTO.getCorpid());
            param.put("idIn", workflowSortDTO.getWorkflowIdList());
            List<WorkflowEntity> workflowList =  workflowModel.findEntitys(param);
            List<String> versionList = new ArrayList<>();
            Map<Long, WorkflowEntity> workflowMap = new HashMap<>(workflowList.size());
            workflowList.forEach(item->{
                versionList.add(item.getVersion());
                workflowMap.put(item.getId(), item);
            });
            // 获取版本中的工作流列表
            param.clear();
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put(StringConstant.CORPID, workflowSortDTO.getCorpid());
            param.put("versionIn", versionList);
            List<WorkflowEntity> workflowVersionList =  workflowModel.findEntitys(param);

            Integer sort = 1;
            Map<String, Integer> versionMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            // 将当前版本的优先级改掉
            for (Long item : workflowSortDTO.getWorkflowIdList()) {
                WorkflowEntity workflowEntity = new WorkflowEntity();
                workflowEntity.setId(item);
                workflowEntity.setPriority(sort);
                WorkflowEntity workflow = workflowMap.get(item);
                versionMap.put(workflow.getVersion(), sort);
                if (Objects.equals(item, workflowSortDTO.getWorkflowId())) {
                    workflowSortVO.setSort(sort);
                }
                workflowEntity.setUpdateTime(DateTimeUtil.getInt());
                sort++;
                list.add(workflowEntity);
            }
            // 将版本里的优先级更改掉
            workflowVersionList.forEach(item->{
                if (!workflowSortDTO.getWorkflowIdList().contains(item.getId())) {
                    WorkflowEntity workflowEntity = new WorkflowEntity();
                    workflowEntity.setId(item.getId());
                    Integer priority = versionMap.get(item.getVersion());
                    workflowEntity.setPriority(priority);
                    workflowEntity.setUpdateTime(DateTimeUtil.getInt());
                    list.add(workflowEntity);
                }
            });
            workflowModel.updatePriority(list, workflowSortDTO.getCorpid());
        } catch (Exception e) {
            LOGGER.error("WorkflowSetServiceImpl.sort error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return workflowSortVO;
    }

    @Override
    public WorkflowUpdateVO update(WorkflowUpdateDTO workflowUpdateDTO) throws XbbException {
        WorkflowUpdateVO workflowUpdateVO = new WorkflowUpdateVO();
        try {
            ProPermissionHelp.verifyPermission(workflowUpdateDTO.getLoginUser(), ProPermissionAliasEnum.PROCESS_SET_UPDATE.getAlias());
            Long workflowId = workflowUpdateDTO.getWorkflowId();
            String corpid = workflowUpdateDTO.getCorpid();
            WorkflowEntity workflow = workflowModel.getByKey(workflowId, corpid);

            WorkflowEntity workflowEntity = new WorkflowEntity();
            workflowEntity.setId(workflowId);
            workflowEntity.setCorpid(corpid);
            workflowEntity.setEmptyApproverType(workflowUpdateDTO.getEmptyApproverType());
            workflowEntity.setAllowViewLog(workflowUpdateDTO.getAllowViewLog());
            workflowEntity.setAllowWithdraw(workflowUpdateDTO.getAllowWithdraw());
            workflowEntity.setApproverDedup(workflowUpdateDTO.getApproverDedup());
            workflowEntity.setAllowViewWhole(workflowUpdateDTO.getAllowViewWhole());
            workflowEntity.setAutoApprovedPass(workflowUpdateDTO.getAutoApprovedPass());
            if (workflowUpdateDTO.getRolesWithoutApprove() == null) {
                workflowUpdateDTO.setRolesWithoutApprove(new ArrayList<>());
            }
            workflowEntity.setRolesWithoutApprove(JSON.toJSONString(workflowUpdateDTO.getRolesWithoutApprove()));

            workflowModel.update(workflowEntity);

            saveAllowEditAfterFinished(corpid, workflow.getFormId(), workflow.getSaasMark(), workflow.getBusinessType(), workflowUpdateDTO.getAllowEditAfterFinished());
        } catch (Exception e) {
            LOGGER.error("WorkflowSetServiceImpl.update error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return workflowUpdateVO;
    }

    /**
     * 保存审批完成后允许编辑的标识
     * @param corpid
     * @param formId
     * @param saasMark
     * @param businessType
     * @param allowEditAfterFinished
     * @throws XbbException
     */
    @Override
    public void saveAllowEditAfterFinished(String corpid, Long formId, Integer saasMark, Integer businessType, Integer allowEditAfterFinished) throws XbbException {
        String alias = RedisPrefixConstant.ALLOW_EDIT_AFTER_FINISHED;
        FormConfigEntity formConfigEntity = formConfigModel.getByConfig(alias, corpid, formId, saasMark, businessType);
        allowEditAfterFinished = allowEditAfterFinished == null ? 0 : allowEditAfterFinished;
        FormConfigEntity updateFormConfig = new FormConfigEntity(corpid, formId, saasMark, businessType, alias, allowEditAfterFinished.toString());
        if (Objects.nonNull(formConfigEntity)) {
            updateFormConfig.setId(formConfigEntity.getId());
        }
        formConfigModel.save(updateFormConfig);
    }

    @Override
    public WorkflowLinkListVO linkList(WorkflowLinkListDTO workflowLinkListDTO) throws XbbException {
        String corpid = workflowLinkListDTO.getCorpid();

        WorkflowEntity workflowEntity = workflowModel.getByKey(workflowLinkListDTO.getWorkflowId(), corpid);
        if (Objects.isNull(workflowEntity)) {
            throw new XbbException(ProErrorCodeEnum.API_ERROR_260037);
        }

        Map<String, Object> param = new HashMap<>();
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        param.put(ParameterConstant.ENABLE, BasicConstant.ONE);
        param.put(ParameterConstant.FORMID, workflowEntity.getFormId());
        List<StageProcessEntity> stageProcessEntities = stageProcessModel.findEntitys(param);
        Map<Long, StageProcessEntity> stageProcessAndNameMap = stageProcessEntities.stream().collect(Collectors.toMap(StageProcessEntity::getId, v -> v, (v1, v2) -> v1));

        param.clear();
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("workflowId", workflowLinkListDTO.getWorkflowId());
        param.put("stageProcessIdIn", stageProcessAndNameMap.keySet());
        PageHelper pageHelper = PageHelperUtil.getPageHelper(param, stageWorkflowModel, workflowLinkListDTO.getPage(), workflowLinkListDTO.getPageSize());
        List<StageWorkflowEntity> stageWorkflowEntities = (List<StageWorkflowEntity>) PageHelperUtil.getEntityList(param, pageHelper, stageWorkflowModel);

        List<Long> stageIds = new ArrayList<>();
        stageWorkflowEntities.forEach(v -> {
            stageIds.add(v.getStageId());
            stageIds.add(v.getRelatedStageId());
        });

        StageHandle stageHandle = stageHandleFactory.getStageHandle(workflowEntity.getSaasMark(), workflowEntity.getBusinessType());

        param.clear();
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        param.put(ParameterConstant.ID_IN, stageIds);
        List<PaasStageEntity> paasStageModelEntitys = stageHandle.findEntitys(param);
        Map<Long, String> stageAndNameMap = paasStageModelEntitys.stream().collect(Collectors.toMap(PaasStageEntity::getId, PaasStageEntity::getName, (v1, v2) -> v1));

        WorkflowLinkListVO workflowLinkListVO = new WorkflowLinkListVO();

        List<WorkflowLinkListVO.WorkflowLinkListPojo> workflowLinkListPojos = new ArrayList<>();
        for (StageWorkflowEntity stageWorkflowEntity : stageWorkflowEntities) {
            WorkflowLinkListVO.WorkflowLinkListPojo workflowLinkListPojo = new WorkflowLinkListVO.WorkflowLinkListPojo();
            workflowLinkListPojo.setId(stageWorkflowEntity.getId());
            workflowLinkListPojo.setType(WorkflowLinkBusinessTypeEnum.stage_type.getName());
            workflowLinkListPojo.setCondition(StageWorkflowTriggerTypeEnum.getNameByCode(stageWorkflowEntity.getTriggerType()));
            StageProcessEntity stageProcessEntity = stageProcessAndNameMap.get(stageWorkflowEntity.getStageProcessId());
            // 不启用的不展示
            if (Objects.isNull(stageProcessEntity)) {
                continue;
            }
            workflowLinkListPojo.setName(stageProcessEntity.getName());
            workflowLinkListPojo.setVersion(stageProcessEntity.getVersionName());
            workflowLinkListPojo.setStage(stageAndNameMap.getOrDefault(stageWorkflowEntity.getStageId(), ""));
            if (Objects.equals(stageWorkflowEntity.getTriggerType(), StageWorkflowTriggerTypeEnum.BEFORE_STAGE.getCode())) {
                workflowLinkListPojo.setFromStage(stageAndNameMap.getOrDefault(stageWorkflowEntity.getRelatedStageId(), ""));
                workflowLinkListPojo.setToStage("");
            } else {
                workflowLinkListPojo.setFromStage("");
                workflowLinkListPojo.setToStage(stageAndNameMap.getOrDefault(stageWorkflowEntity.getRelatedStageId(), ""));
            }
            workflowLinkListPojos.add(workflowLinkListPojo);
        }
        workflowLinkListVO.setList(workflowLinkListPojos);
        workflowLinkListVO.setPageHelper(pageHelper);
        return workflowLinkListVO;
    }

    @Override
    public WorkflowVersionListVO versionList(WorkflowVersionListDTO workflowVersionListDTO) throws XbbException {
        WorkflowVersionListVO workflowVersionListVO = new WorkflowVersionListVO();
        try {
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID, workflowVersionListDTO.getCorpid());
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("isArchive", workflowVersionListDTO.getArchive());
            param.put("version", workflowVersionListDTO.getVersion());
            param.put("orderByStr", " version_id " + SortOrder.ASC);
            PageHelper pageHelper = PageHelperUtil.getPageHelper(param, workflowModel, workflowVersionListDTO.getPage(), workflowVersionListDTO.getPageSize());
            List<WorkflowEntity> workflowList = (List<WorkflowEntity>) PageHelperUtil.getEntityList(param, pageHelper, workflowModel);
            List<WorkflowVersionPojo> list = new ArrayList<>();
            List<Long> workflowIdList = new ArrayList<>();
            workflowList.forEach(item->workflowIdList.add(item.getId()));
            param.clear();
            param.put(StringConstant.CORPID, workflowVersionListDTO.getCorpid());
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("workflowIdIn", workflowIdList);
            param.put("columns", " DISTINCT(workflow_id) ");
            List<WorkflowTaskEntity> taskList = workflowTaskModel.findEntities(param);
            Set<Long> haveTaskSet = new HashSet<>();
            taskList.forEach(item->haveTaskSet.add(item.getWorkflowId()));
            workflowList.forEach(item->{
                WorkflowVersionPojo workflowVersionPojo = new WorkflowVersionPojo();

                workflowVersionPojo.setWorkflowId(item.getId());
                workflowVersionPojo.setVersionName(item.getVersionName());
                workflowVersionPojo.setVersionId(item.getVersionId());
                workflowVersionPojo.setVersion(item.getVersion());
                workflowVersionPojo.setCurrentVersion(item.getCurrentVersion());
                if (Objects.equals(workflowVersionListDTO.getArchive(), BasicConstant.TWO)) {
                    if (StringUtil.isEmpty(item.getVersionName())) {
                        workflowVersionPojo.setVersionName("v1");
                    }
                    if (item.getVersionId() == null) {
                        workflowVersionPojo.setVersionId(1);
                    }
                    if (Objects.equals(item.getEnable(), 1)) {
                        // 启用状态时，把启用的版本放在第一位
                        workflowVersionPojo.setVersionType(2);
                        list.add(0, workflowVersionPojo);
                    } else if (Objects.equals(item.getCurrentVersion(), 1)) {
                        // 未启用状态时，把当前版本放在第一位
                        list.add(0, workflowVersionPojo);
                        if (haveTaskSet.contains(item.getId())) {
                            workflowVersionPojo.setVersionType(3);
                        }else {
                            workflowVersionPojo.setVersionType(1);
                        }
                    } else {
                        if (haveTaskSet.contains(item.getId())) {
                            workflowVersionPojo.setVersionType(3);
                        }else {
                            workflowVersionPojo.setVersionType(1);
                        }
                        list.add(workflowVersionPojo);
                    }
                }else {
                    list.add(workflowVersionPojo);
                }
            });
            workflowVersionListVO.setList(list);
            workflowVersionListVO.setPageHelper(pageHelper);
        } catch (Exception e) {
            LOGGER.error("WorkflowSetServiceImpl.update error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return workflowVersionListVO;
    }


    @Override
    public WorkflowArchiveVO archive(WorkflowArchiveDTO workflowArchiveDTO) throws XbbException {
        try {
            // 获取相应的归档状态的数量
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID, workflowArchiveDTO.getCorpid());
            param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            param.put("version", workflowArchiveDTO.getVersion());
            param.put("isArchive", BasicConstant.TWO);
            Integer noArchive = workflowModel.getEntitysCount(param);
            if (Objects.equals(1, workflowArchiveDTO.getArchive()) && noArchive == 1){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NON_ARCHIVE_LEAST);
            }
            param.put("isArchive", BasicConstant.ONE);
            Integer count = workflowModel.getEntitysCount(param);
            // 未归档版本限制500个
            if (count >= NONE_ARCHIVE){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_ARCHIVE_MAX_LIMIT);
            }
            WorkflowEntity workflowEntity = new WorkflowEntity();
            workflowEntity.setId(workflowArchiveDTO.getWorkflowId());
            workflowEntity.setCorpid(workflowArchiveDTO.getCorpid());
            workflowEntity.setIsArchive(workflowArchiveDTO.getArchive());
            workflowModel.update(workflowEntity);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("WorkflowSetServiceImpl.update error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return new WorkflowArchiveVO();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public WorkflowNewVersionVO newVersion(WorkflowNewVersionDTO workflowNewVersionDTO) throws XbbException {
        WorkflowNewVersionVO workflowNewVersionVO = new WorkflowNewVersionVO();
        try {
            ProPermissionHelp.verifyPermission(workflowNewVersionDTO.getLoginUser(), ProPermissionAliasEnum.PROCESS_SET_UPDATE.getAlias());
            Long workflowId = workflowNewVersionDTO.getWorkflowId();
            String corpid = workflowNewVersionDTO.getCorpid();
            WorkflowEntity workflowEntity = workflowModel.getByKey(workflowId, corpid);
            if (Objects.isNull(workflowEntity)) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260037);
            }
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("orderByStr", " version_id DESC ");
            params.put(StringConstant.CORPID, corpid);
            params.put(StringConstant.FORM_ID, workflowEntity.getFormId());
            params.put(StringConstant.SAAS_MARK, workflowEntity.getSaasMark());
            params.put(StringConstant.BUSINESS_TYPE, workflowEntity.getBusinessType());
            params.put("version", workflowEntity.getVersion());
            params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            List<WorkflowEntity> workflowList = workflowModel.findEntitys(params);
            int versionId = 1;
            Integer count = 1;
            for (WorkflowEntity item : workflowList) {
                if (Objects.equals(item.getIsArchive(), BasicConstant.TWO)) {
                    count++;
                }
            }
            if (workflowList.size() > WORKFLOW_MAX) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_SIZE_MAX_LIMIT);
            }
            if (count > WORKFLOW_ISARCHIVE_MAX){
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.PROCESS_NON_ARCHIVE_MAX_LIMIT);
            }
            // 将当前新建的工作流设置为最新版本
            if (CollectionsUtil.isNotEmpty(workflowList)) {
                versionId = workflowList.get(0).getVersionId() + 1;
            }
            String userId = workflowNewVersionDTO.getUserId();
            Long now = DateTimeUtil.getInt();
            workflowEntity.setId(null);
            workflowEntity.setAddTime(now);
            workflowEntity.setUpdateTime(now);
            workflowEntity.setEnable(0);
            workflowEntity.setCurrentVersion(0);
            workflowEntity.setVersionId(versionId);
            workflowEntity.setVersionName("v"+versionId);
            workflowEntity.setCreatorId(userId);
            workflowModel.insert(workflowEntity);
            Long newWorkflowId = workflowEntity.getId();
            params.clear();
            params.put(StringConstant.CORPID, corpid);
            params.put("workflowId", workflowId);
            params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            List<WorkflowNodeEntity> nodeList = workflowNodeModel.findEntitys(params);
            List<WorkflowNodeEntityExt> insertList = new ArrayList<>();

            nodeList.forEach(item->{
                WorkflowNodeEntityExt workflowNodeEntityExt = new WorkflowNodeEntityExt(corpid, item.getName(), item.getTriggerType(), item.getType(), item.getAppId(), item.getFormId(), item.getMenuId(),
                        item.getSaasMark(), item.getBusinessType(), newWorkflowId,  item.getUid(), item.getPrevId(), item.getWrapperId(), item.getPriority(), item.getConfigData());
                workflowNodeEntityExt.setWorkflowNodeId(item.getId());
                insertList.add(workflowNodeEntityExt);
            });
            workflowNodeModel.insertExtBatch(insertList);
            Map<Long, Long> workflowNodeMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            insertList.forEach(item->{
                workflowNodeMap.put(item.getWorkflowNodeId(), item.getId());
            });
            for (WorkflowNodeEntityExt item : insertList) {
                WorkflowNodeSettings workflowNodeSettings = workflowNodeSettingsMap.get(item.getType());
                workflowNodeSettings.replaceWorkflowNodeId(item, workflowNodeMap);
            }
            workflowNodeModel.updateConfigData(insertList, corpid);
            workflowNewVersionVO.setWorkflowId(newWorkflowId);
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("WorkflowSetServiceImpl.newVersion error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return workflowNewVersionVO;
    }

    @Override
    public WorkflowDeleteVersionVO deleteVersion(WorkflowDeleteVersionDTO workflowDeleteVersionDTO) throws XbbException {
        WorkflowDeleteVersionVO workflowDeleteVersionVO = new WorkflowDeleteVersionVO();
        try {
            Long workflowId = workflowDeleteVersionDTO.getWorkflowId();
            String corpid = workflowDeleteVersionDTO.getCorpid();
            WorkflowEntity workflowEntity = workflowModel.getByKey(workflowId, corpid);
            if (Objects.isNull(workflowEntity)) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260037);
            }
            if (Objects.equals(1, workflowEntity.getEnable())) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260038);
            }
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put(StringConstant.CORPID, corpid);
            params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
            params.put("workflowId", workflowId);
            Integer count = workflowTaskModel.getEntityCount(params);
            if (count > 0) {
                throw new XbbException(ProErrorCodeEnum.API_ERROR_260045);
            }
            workflowModel.deleteByKey(workflowId, corpid);

            String workflowMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_DELETE_WORK), workflowDeleteVersionDTO.getLoginUserName(),
                    OperateModuleTypeEnum.WORKFLOW.getName(), workflowEntity.getName());
            mongoLogHelp.saveLoggerByInsert(corpid, workflowDeleteVersionDTO.getUserId(), workflowDeleteVersionDTO.getLoginUserName(), workflowEntity.getName(), workflowMemo,
                    workflowId.toString(), workflowDeleteVersionDTO.getHttpHeader(), OperateModuleTypeEnum.WORKFLOW, OperateTypeEnum.DELETE);

            // 删除工作流的节点
            workflowNodeModel.deleteByWorkflowId(Collections.singletonList(workflowId), corpid);
            if (Objects.equals(1, workflowEntity.getCurrentVersion())) {
                params.clear();
                params.put(StringConstant.CORPID, corpid);
                params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
                params.put("version", workflowEntity.getVersion());
                params.put("orderByStr", "version_id desc");
                params.put("pageNum", 1);
                List<WorkflowEntity> list = workflowModel.findEntitys(params);
                if (CollectionUtils.isNotEmpty(list)) {
                    WorkflowEntity otherWorkflow = list.get(0);
                    WorkflowEntity updateWorkflow = new WorkflowEntity();
                    updateWorkflow.setId(otherWorkflow.getId());
                    updateWorkflow.setCorpid(corpid);
                    updateWorkflow.setCurrentVersion(1);
                    workflowModel.update(updateWorkflow);
                }
            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            LOGGER.error("WorkflowSetServiceImpl.deleteVersion error：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
        return workflowDeleteVersionVO;
    }

    /**
     * 更改表单审批标识和菜单的菜单类型
     * @param workflowEntity 工作流实体，
     * @param enable 是否启用 1：启用；0：不启用
     * @param workflowEnableDTO
     * @throws XbbException
     */
    private void updateFormType(WorkflowEntity workflowEntity, Integer enable, WorkflowEnableDTO workflowEnableDTO) throws XbbException {
        String corpid = workflowEnableDTO.getCorpid();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("isApprove", 1);
        param.put(StringConstant.FORM_ID, workflowEntity.getFormId());
        param.put(StringConstant.SAAS_MARK, workflowEntity.getSaasMark());
        param.put(StringConstant.BUSINESS_TYPE, workflowEntity.getBusinessType());
        param.put("enable", 1);
        Integer count = workflowModel.getEntitysCount(param);
        // 将表单的审批标识和菜单的菜单类型更改下
        boolean hasProcess = (Objects.equals(1, enable) && Objects.equals(workflowEntity.getIsApprove(), 1)) || count > 0;
        Integer isProcessForm = hasProcess ? 1: 0;
        Integer type =  hasProcess ? MenuTypeEnum.PROCESS_FORM.getType(): MenuTypeEnum.FORM.getType();
        String formName = "";
        OperateModuleTypeEnum operateModuleType = null;
        if (Objects.equals(XbbRefTypeEnum.WORK_ORDER.getCode(), workflowEntity.getBusinessType())) {
            WorkOrderFormEntity workOrderFormEntity = workOrderFormModel.getByKey(workflowEntity.getFormId(), corpid);
            if (Objects.nonNull(workOrderFormEntity)) {
                formName = workOrderFormEntity.getName();
                WorkOrderFormEntity updateFormEntity = new WorkOrderFormEntity();
                updateFormEntity.setCorpid(corpid);
                updateFormEntity.setId(workflowEntity.getFormId());
                updateFormEntity.setIsProcessForm(isProcessForm);
                workOrderFormModel.update(updateFormEntity);
                operateModuleType = OperateModuleTypeEnum.PAAS_FORM_WORK_ORDER;
            }
        } else {
            PaasFormEntity paasFormEntity = paasFormModel.getByKey(workflowEntity.getFormId(), corpid);
            if (Objects.nonNull(paasFormEntity)) {
                formName = paasFormEntity.getName();
                paasFormEntity = new PaasFormEntity();
                paasFormEntity.setCorpid(corpid);
                paasFormEntity.setId(workflowEntity.getFormId());
                paasFormEntity.setIsProcessForm(isProcessForm);
                paasFormModel.update(paasFormEntity);
                operateModuleType = OperateModuleTypeEnum.PAAS_FORM;
            }
        }
        String userName = workflowEnableDTO.getLoginUserName();
        String userId = workflowEnableDTO.getUserId();
        // 记录日志
        if (Objects.nonNull(operateModuleType)) {
            String isProcessFormStr = Objects.equals(isProcessForm, 1) ? MenuTypeEnum.PROCESS_FORM.getMemo() : MenuTypeEnum.FORM.getMemo();
            String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_FORM_TYPE), userName, formName, isProcessFormStr);
            mongoLogHelp.buildLog(corpid, userId, userName, operateModuleType, OperateTypeEnum.EDIT, workflowEntity.getFormId().toString(), formName, memo, workflowEnableDTO.getHttpHeader());
        }
        Map<Integer, String> groupTypeMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        groupTypeMap.put(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), XbbRefTypeEnum.CUSTOMER.getAlias());
        groupTypeMap.put(XbbRefTypeEnum.SALES_OPPORTUNITY.getCode(), XbbRefTypeEnum.ALL_OPPORTUNITY.getAlias());
        groupTypeMap.put(XbbRefTypeEnum.CLUE.getCode(), XbbRefTypeEnum.ALL_CLUE.getAlias());
        PaasMenuEntity paasMenuEntity;
        if (groupTypeMap.containsKey(workflowEntity.getBusinessType())) {
            paasMenuEntity = paasMenuModel.getByAlias(groupTypeMap.get(workflowEntity.getBusinessType()), corpid);
        } else {
            paasMenuEntity = paasMenuModel.getByKey(workflowEntity.getMenuId(), corpid);
        }
        if (Objects.isNull(paasMenuEntity)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.MENU_NOT_EXIST);
        }
        PaasMenuEntity updateMenu = new PaasMenuEntity();
        updateMenu.setId(paasMenuEntity.getId());
        updateMenu.setCorpid(corpid);
        updateMenu.setType(type);
        paasMenuModel.update(updateMenu);
        // 记录日志
        String isProcessFormStr = Objects.equals(isProcessForm, 1) ? MenuTypeEnum.PROCESS_FORM.getMemo() : MenuTypeEnum.FORM.getMemo();
        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_MENU_TYPE), userName, paasMenuEntity.getName(), isProcessFormStr);
        mongoLogHelp.buildLog(corpid, userId, userName, OperateModuleTypeEnum.PAAS_MENU, OperateTypeEnum.EDIT, paasMenuEntity.getId().toString(), paasMenuEntity.getName(), memo, workflowEnableDTO.getHttpHeader());

    }


}
